home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Light ROM 1
/
LIGHT-ROM 1 (Amiga Library Services)(1994).iso
/
ffdisks
/
d941.lha
/
YAMFG
/
Source
/
YAMFG.FraníÂis
< prev
next >
Wrap
Text File
|
1993-12-20
|
27KB
|
869 lines
; YAMFG 1.0 - ©1993 F.Delacroix- FreeWare
; écrit sur le Devpac 3 d'Hisoft
; tous les includes system ont été ajoutés au moment de l'as-
; semblage grâce à un fichier .gs de Devpac 3. Si vous utili-
; sez un autre assembleur,ajoutez-les manuellement.
include exec/execbase.i ; d'autres includes: struct ExecBase
include hardware/custom.i ; custom hardware: nombres aléatoires
include libraries/reqtools.i ; includes pour reqtools.library
include libraries/reqtools_lib.i
DEFAULT_WIDTH EQU 20 ; constantes utiles: évidentes
DEFAULT_HEIGHT EQU 20
DEFAULT_MINES EQU 40
MAX_WIDTH EQU 24
MAX_HEIGHT EQU 21
UP EQU $4c ; touches utilisées pour bouger le tank
DOWN EQU $4d
RIGHT EQU $4e
LEFT EQU $4f
STATUSX EQU 4 ; coordonnées pour la ligne status
STATUSY EQU 18
move.l 4.w,a6
move.l ThisTask(a6),a4 ;trouve la tâche (même chose que FindTask(0))
moveq #0,d0
tst.l pr_CLI(a4) ; venons-nous du CLI ?
bne.s FromCLI ; oui...
lea pr_MsgPort(a4),a0 ; non: allons chercher le message
jsr _LVOWaitPort(a6) ; WBStartup envoyé par le Workbench
lea pr_MsgPort(a4),a0
jsr _LVOGetMsg(a6)
FromCLI move.l d0,WBStarter ; et rangeons-le (0 pour le CLI)
lea ReqTools.Name(pc),a1 ; ouvrons la reqtools.library
moveq #0,d0
jsr _LVOOpenLibrary(a6)
move.l d0,ReqTools.Base
beq OutOfHere ; pas de reqtools.library: fin du programme
move.l ReqTools.Base(pc),a0 ; et prenons-y les bases des autres
move.l rt_IntuitionBase(a0),Intuition.Base ; bibliothèques
move.l rt_GfxBase(a0),Graphics.Base
lea YAMFG.NewWindow(pc),a0 ; ouvrons la fenêtre
move.l Intuition.Base(pc),a6
jsr _LVOOpenWindow(a6)
move.l d0,YAMFG.Window
beq CloseReqTools ; pas de fenêtre !
move.l YAMFG.Window(pc),a0 ; attachons les menus à la fenêtre
lea Project.Menu(pc),a1
jsr _LVOSetMenuStrip(a6)
tst.l d0
beq CloseWindow ; raté ! (ne devrait pas arriver)
move.l YAMFG.Window(pc),a0 ; données importantes pour la fenêtre
move.l wd_RPort(a0),YAMFG.RastPort ; RastPort pour les graphismes
move.l wd_UserPort(a0),YAMFG.UserPort ; UserPort pour les messages
bra NewGame ; commençons une nouvelle partie
WaitMessage
move.l YAMFG.UserPort(pc),a0 ; attends un message envoyé par
move.l 4.w,a6 ; Intuition à notre fenêtre...
jsr _LVOWaitPort(a6)
NextMessage
move.l YAMFG.UserPort(pc),a0 ; et vas le chercher!
move.l 4.w,a6
jsr _LVOGetMsg(a6)
tst.l d0
beq.s WaitMessage ; Y en a-t-il vraiment un ?
move.l d0,a1 ; Oui !
move.l im_Class(a1),d7 ; Sauve les champs importants:Classe
move.w im_Code(a1),d6 ; et Code
jsr _LVOReplyMsg(a6) ; et réponds à Intuition
cmp.l #IDCMP_CLOSEWINDOW,d7 ; Devons-nous quitter ?
beq ClearMenus ; Oui? Alors partons...
cmp.w #IDCMP_RAWKEY,d7 ; A-t-on appuyé sur une touche?
bne NoRawKey
btst #IECODEB_UP_PREFIX,d6 ; ignore si une touche a été lachée
bne NextMessage
tst.b FinishFlag ; Le jeu est-il terminé ?
bne NewGame ; oui? alors commence une nouvelle partie
move.w MinerX(pc),d0 ; non: prend la position du tank
move.w MinerY(pc),d1
cmp.w #UP,d6 ; Haut ?
beq.s GoUp
cmp.w #DOWN,d6 ; Bas ?
beq.s GoDown
cmp.w #RIGHT,d6 ; Droite ?
beq.s GoRight
cmp.w #LEFT,d6 ; Ou gauche ?
bne NextMessage ; Rien de cela ?? alors prochain message
subq.w #1,d0 ; 1 case à gauche
bra.s DirectionGot
GoRight addq.w #1,d0 ; 1 case à droite
bra.s DirectionGot
GoDown addq.w #1,d1 ; 1 case en bas
bra.s DirectionGot
GoUp subq.w #1,d1 ; 1 case en haut
DirectionGot
bsr CheckBounds ; voyons si le tank ne sort pas des limites
bsr MoveMiner ; puis déplaçons-le
move.l Width(pc),d0 ; le tank est-il sur le bord droit ?
subq.l #1,d0
cmp.w MinerX(pc),d0
bne.s NoGoal
move.l Height(pc),d0 ; le tank est-il en bas ?
subq.l #1,d0
cmp.w MinerY(pc),d0
bne.s NoGoal ; oui ! le but est atteint ! (Félicitations!)
lea Won.MSG(pc),a0 ; Affiche le message de fin
bra.s EndOfGame ; et termine le jeu
NoGoal moveq #0,d0 ; But pas encore atteint
move.w MinerY(pc),d0 ; Transforme la position du tank en un offset
mulu Width+2(pc),d0 ; pour la matrice: offset=Width*Y+X
add.w MinerX(pc),d0
lea Mines.Array(pc),a2
tst.b (a2,d0) ; Regarde si le tank est sur une mine
beq.s ShowNumber ; Non!!
lea Lost.MSG(pc),a0 ; Uh-Oh: une mine !
EndOfGame
st FinishFlag ; Le jeu est terminé
bsr DisplayStatus ; Affiche le message de fin (gagné ou perdu)
bsr RevealMines ; et révèle la position des mines
bra NextMessage ; Reboucle
NewGame
clr.b FinishFlag ; Quand un jeu commence,il n'est pas fini
move.l YAMFG.RastPort(pc),a1
moveq #RP_JAM2,d0
move.l Graphics.Base(pc),a6
jsr _LVOSetDrMd(a6) ; mode de dessin:RP_JAM2 (deux couleurs)
move.l YAMFG.RastPort(pc),a1
moveq #0,d0
jsr _LVOSetAPen(a6) ; choisit couleur 0
move.l YAMFG.RastPort(pc),a1
move.l #4,d0 ; dessine un gros rectange pour effacer l'affichage
move.l #12,d1
move.l #396,d2
move.l #196,d3
jsr _LVORectFill(a6)
bsr DrawMinesBorder ; dessine un border autour de l'aire de jeu
bsr PlaceMines ; Génère les positions aléatoires des mines
clr.w MinerX ; Place le tank dans le coin supérieur gauche
clr.w MinerY
bsr ShowMiner ; dessine le tank
ShowNumber
lea Mines.Array(pc),a2
moveq #0,d0
move.w MinerY(pc),d0 ; change la position du tank en offset
mulu Width+2(pc),d0
add.w MinerX(pc),d0
add.l d0,a2 ; position du tank dans la matrice
moveq #0,d1
move.l Width(pc),d3 ; d3=Largeur de l'aire de jeu
move.l Height(pc),d4
move.l d3,d5 ; d5=Largeur-1
subq.l #1,d5
subq.l #1,d4 ; d4=Hauteur-1
move.l d3,d6
neg.l d6 ; d6=-Largeur
tst.w MinerY ; tank sur le bord haut ?
beq.s No9 ; oui? alors ne teste pas au-dessus!
tst.b (a2,d6.l) ; mine en position 8 ?
beq.s No8 ; note: Je suis ces conventions dans le
addq.l #1,d1 ; source: 789
No8 tst.w MinerX ; 4 6
beq.s No7 ; 123
tst.b -1(a2,d6.l) ; si la grille dans la position testée (par
beq.s No7 ; ordre d'apparition:8,7,9,4,6,1,2,3) ne
addq.l #1,d1 ; contient pas zero,alors il y a une mine,et
No7 cmp.w MinerX(pc),d5 ; Le compteur de mines (d1) est incrémenté
beq.s No9 ; Bien sûr,si la position n'existe pas
tst.b 1(a2,d6.l) ; (si le tank est sur un bord de l'aire de
beq.s No9 ; jeu),la position n'est pas testée.
addq.l #1,d1
No9 tst.w MinerX
beq.s No4
tst.b -1(a2)
beq.s No4
addq.l #1,d1
No4 cmp.w MinerX(pc),d5
beq.s No6
tst.b 1(a2)
beq.s No6
addq.l #1,d1
No6 cmp.w MinerY(pc),d4
beq.s No3
tst.w MinerX
beq.s No1
tst.b -1(a2,d3)
beq.s No1
addq.l #1,d1
No1 tst.b (a2,d3)
beq.s No2
addq.l #1,d1
No2 cmp.w MinerX(pc),d5
beq.s No3
tst.b 1(a2,d3)
beq.s No3
addq.l #1,d1
No3
add.b #'0',d1 ; change le compteur de mines en un chiffre affichable
move.b d1,Mines.Number ; et range-le pour l'afficher
lea MinesNumber.MSG(pc),a0 ; Le message 'Mines around you'
bsr DisplayStatus ; affiche-le!
bra NextMessage ; prochaine action du joueur...
NoRawKey
cmp.l #IDCMP_MENUPICK,d7 ; un menu sélectionné ?
bne NextMessage ; non: ignore ce message étrange!
DoNextSelect
move.w d6,d0 ; le menu number donné par Intuition
lea Project.Menu(pc),a0 ; notre barre de menu
move.l Intuition.Base(pc),a6
jsr _LVOItemAddress(a6) ; adresse du MenuItem choisi
move.l d0,a5
tst.l d0 ; y en a-t-il vraiment un ?
beq NextMessage ; Non: fin du traitement des menus
move.w mi_NextSelect(a5),d6 ; stocke le menunumber suivant
move.l mi_SIZEOF(a5),a1 ; Ceci est un champ non standard de
cmp.l #0,a1 ; la structure MenuItem: la routine à executer...
beq DoNextSelect ; si il y en a une bien sûr
jsr (a1) ; execute-la !
bra.s DoNextSelect ; puis examine la sélection suivante
ClearMenus ; Temps de quitter le jeu !!
move.l YAMFG.Window(pc),a0 ; retire les menus de la fenêtre
move.l Intuition.Base(pc),a6
jsr _LVOClearMenuStrip(a6)
CloseWindow
move.l YAMFG.Window(pc),a0 ; ferme la fenêtre
move.l Intuition.Base(pc),a6
jsr _LVOCloseWindow(a6)
CloseReqTools
move.l ReqTools.Base(pc),a1 ; ferme la reqtools.library
move.l 4.w,a6
jsr _LVOCloseLibrary(a6)
OutOfHere
move.l WBStarter(pc),d1 ; venons-nous du Workbench ?
beq.s BackToCLI ; non: plus rien à faire
jsr _LVOForbid(a6) ; oui: nous devons répondre au message
move.l d1,a1 ; WBStartup que nous avons reçu au début
move.l 4.w,a6 ; notez que Forbid() est absolument nécessaire
jsr _LVOReplyMsg(a6)
BackToCLI
moveq #0,d0 ; pour que le CLI n'affiche pas d'étranges codes
rts ; C'est la triste fin ...
; sous-routine qui initialise quelques variables d'affichage et dessine
; un bord rectangulaire et affiche l'image de la cible
DrawMinesBorder
movem.l d0-d1/a0-a1/a6,-(sp)
move.l Width(pc),d0 ; Largeur en pixels=Largeur*16
lsl.l #4,d0
move.l Height(pc),d1 ; Hauteur en pixels=Hauteur*8
lsl.l #3,d1
addq.l #1,d0
addq.l #1,d1
move.w d0,Border.Right1 ; stocke ces valeurs pour dessiner
move.w d0,Border.Right2 ; le cadre
move.w d0,Border.Right3
move.w d1,Border.Bot1
move.w d1,Border.Bot2
move.w d1,Border.Bot3
move.l YAMFG.RastPort(pc),a0 ; le RastPort de la fenêtre
lea YAMFG.Border(pc),a1 ; la structure Border
move.l Width(pc),d0 ; Calcule la variable PlayX pour centrer
lsl.l #3,d0 ; l'aire de jeu: PlayX=(400-Width*16)/2
neg.l d0 ; PlayX=200-Width*8
add.l #200,d0
move.l d0,PlayX
move.l Height(pc),d1 ; Calcule PlayY de façon similaire
lsl.l #2,d1 ; PlayY=(200-Height*8)/2=100-Height*4
neg.l d1
add.l #100,d1
addq.l #3,d1 ; et ajoute 3 pixels
cmp.l #STATUSY+4,d1 ; mais ne déborde pas sur la ligne de status
bge.s NotTooLow
move.l #STATUSY+4,d1 ; Si c'est le cas,descends un peu
NotTooLow
move.l d1,PlayY
move.l Intuition.Base(pc),a6
jsr _LVODrawBorder(a6) ; Dessine-le,ce cadre
move.l YAMFG.RastPort(pc),a0 ; Nécessaire pour tous les graphismes
lea Target.Image,a1 ; La structure image pour la cible
move.l Width(pc),d0 ; position X Y de la cible
subq.l #1,d0 ; dans le coin inférieur droit
lsl.l #4,d0
add.l PlayX(pc),d0
move.l Height(pc),d1
subq.l #1,d1
lsl.l #3,d1
add.l PlayY(pc),d1
jsr _LVODrawImage(a6) ; Intuition la dessine.
movem.l (sp)+,d0-d1/a0-a1/a6
rts
; ceci est la routine qui place aléatoirement les mines dans la grille
; il n'est PAS garanti qu'il y ait moyen de passer si les mines sont trop
; nombreuses. La routine utilise un algorythme FastRand() classique,avec
; la position du raster pour graine
PlaceMines
movem.l d0/d3-d5/a2,-(sp)
lea Mines.Array(pc),a2 ; grille à remplir
move.l Width(pc),d0
mulu Height+2(pc),d0 ; Taille de la grille
move.l d0,d3
subq.l #1,d0 ; une boucle dbra décompte jusqu'à -1
ClearMines
clr.b (a2)+ ; enlève toutes les mines de la grille
dbra d0,ClearMines
moveq #0,d5
move.w $DFF000+vhposr,d5 ; obtient la graine de la position raster
lea Mines.Array(pc),a2 ; récupère a2
move.l Mines(pc),d4 ; nombre de mines à placer
cmp.l d4,d3 ; est-ce possible ??
bgt.s AnotherRandom ; oui
move.l d3,d4 ; il y a beaucoup trop de mines !! Réduis leur nombre
subq.l #4,d4 ; c'est seulement une sécurité:qui jouerait une partie
AnotherRandom ; où chaque mouvement est perdu ?
add.l d5,d5 ; Voici la routine FastRand() qui génère une série
bhi.s .NoEOR ; de nombres apparamment aléatoire
eor.l #$1D872B41,d5 ; Pourquoi ce nombre ? Bonne question.
.NoEOR
moveq #0,d0 ; divise le nombre aléatoire par la taille de la
move.w d5,d0 ; grille pour que le reste soit une position valide
divu d3,d0
swap d0
tst.w d0 ; Pas de mine dans le coin supérieur gauche
beq AnotherRandom
tst.b (a2,d0.w) ; Y a-t-il déjà une mine ici ?
bne.s AnotherRandom ; Oui?? Alors utilise un autre offset
move.b #1,(a2,d0.w) ; Non: maintenant y en a une
subq #1,d4 ; Etait-ce la dernière mine à placer ?
bne AnotherRandom ; Non.
movem.l (sp)+,d0/d3-d5/a2 ; Oui: récupère les registres et
rts ; retourne
; Ceci affiche le tank..
ShowMiner
movem.l d0-d1/a0-a1/a6,-(sp)
move.l YAMFG.RastPort(pc),a0
lea Tank.Image,a1 ; Structure image pour le tank
moveq #0,d0
move.l d0,d1
move.w MinerX(pc),d0
move.w MinerY(pc),d1
lsl.l #4,d0
lsl.l #3,d1
add.l PlayX(pc),d0 ; X=PlayX+MinerX*16
add.l PlayY(pc),d1 ; Y=PlayY+MinerY*8
move.l Intuition.Base(pc),a6
jsr _LVODrawImage(a6) ; Dessine-le. Facile non?
movem.l (sp)+,d0-d1/a0-a1/a6
rts
; Ceci regarde si le tank est sorti des limites,auquel cas il est remis sur
; le bord de la grille. Cette routine est appelée avec la nouvelle position
; souhaitée en D0 et D1 (X et Y respectivement).
CheckBounds
ext.l d0 ; Change l'abscisse en un mot long
cmp.l Width(pc),d0 ; Trop loin sur la droite ?
blt.s NotRightEdge
move.l Width(pc),d0
subq.l #1,d0
NotRightEdge
tst.l d0 ; Trop loin sur la gauche ?
bge.s NotLeftEdge
moveq #0,d0
NotLeftEdge
ext.l d1 ; Change l'ordonnée en un mot long
tst.l d1 ; Trop haut ?
bge.s NotUpEdge
moveq #0,d1
NotUpEdge
cmp.l Height(pc),d1 ; Trop bas ?
blt.s NoDownEdge
move.l Height(pc),d1
subq.l #1,d1
NoDownEdge
rts
; Cette routine efface l'image du tank et la redessine à la position donnée
; par D0 et D1 (X et Y). Elle actualise aussi les variables MinerX et MinerY
MoveMiner
bsr.s EraseMiner
move.w d0,MinerX
move.w d1,MinerY
bra ShowMiner
; Ceci efface l'image du tank en affichant deux espaces en couleur 3
EraseMiner
movem.l d0-d1/a0-a1/a6,-(sp)
move.l YAMFG.RastPort(pc),a1
moveq #0,d0 ; X=PlayX+MinerX*16
move.l d0,d1 ; Y=PlayY+MinerY*8
move.w MinerX(pc),d0
move.w MinerY(pc),d1
lsl.l #4,d0
lsl.l #3,d1
add.l PlayX(pc),d0
add.l PlayY(pc),d1
addq.l #6,d1 ; Ajoute 6 à la position Y pour la ligne de base
move.l Graphics.Base(pc),a6 ; de la fonte topaz standard.
jsr _LVOMove(a6) ; Déplace le curseur graphique
move.l YAMFG.RastPort(pc),a1
moveq #3,d0 ; couleur B égale 3 (orange ou bleu sur les Workbenchs
jsr _LVOSetBPen(a6) ; normalement colorés)
move.l YAMFG.RastPort(pc),a1
moveq #RP_JAM2,d0 ; drawmode: RP_JAM2 pour que les espaces
jsr _LVOSetDrMd(a6) ; soient réellement en bleu
lea Space.Text(pc),a0
move.l YAMFG.RastPort(pc),a1
moveq #2,d0 ; Il y en a deux
jsr _LVOText(a6)
movem.l (sp)+,d0-d1/a0-a1/a6
rts ; That's it
; Cette routine sert à effacer la ligne status. Elle est appelée par DisplayStatus
EraseStatus
movem.l d0-d3/a0-a1/a6,-(sp)
move.l YAMFG.RastPort(pc),a1
moveq #RP_JAM2,d0
move.l Graphics.Base(pc),a6
jsr _LVOSetDrMd(a6) ; Drawmode: RP_JAM2
move.l YAMFG.RastPort(pc),a1
moveq #0,d0 ; couleur A= 0
jsr _LVOSetAPen(a6)
move.l YAMFG.RastPort(pc),a1
move.l #STATUSX,d0 ; coordonnées pour le rectangle qui sera des-
move.l #STATUSY-6,d1 ; siné par dessus la ligne status
move.l #STATUSX+40*8,d2
move.l #STATUSY+2,d3
jsr _LVORectFill(a6) ; dessine le rectangle
movem.l (sp)+,d0-d3/a0-a1/a6
rts
; Cette routine affiche un message dans la ligne status,auparavant effacée.
; A0 est un pointeur sur le message à afficher.
DisplayStatus: ;DisplayStatus(Message)(A0)
movem.l d0-d1/a0-a2/a6,-(sp)
bsr EraseStatus ; Efface d'abord la ligne status
move.l a0,a2 ; Sauve le pointeur sur le message (A2 est obligatoi-
move.l YAMFG.RastPort(pc),a1 ; rement préservé par les librairies)
moveq #RP_JAM1,d0
move.l Graphics.Base(pc),a6
jsr _LVOSetDrMd(a6) ; drawmode: RP_JAM1: seule la couleur A est
move.l YAMFG.RastPort(pc),a1 ; utilisée.
moveq #1,d0
jsr _LVOSetAPen(a6) ; Couleur A=1 (normalement noir ou blanc)
move.l YAMFG.RastPort(pc),a1
move.l #STATUSX,d0 ; Coordonnées de la ligne status
move.l #STATUSY,d1
jsr _LVOMove(a6) ; déplace le curseur graphique
move.l a2,a0
.LenLoop ; compte la longueur du message
tst.b (a2)+ ; nécessaire pour la fonction Text()
bne .LenLoop
sub.l a0,a2
subq.l #1,a2
move.l a2,d0
move.l YAMFG.RastPort(pc),a1
jsr _LVOText(a6) ; affiche le texte
movem.l (sp)+,d0-d1/a0-a2/a6
rts
; Cette routine révèle l'emplacement des mines,appelée quand le jeu est
; terminé (le joueur a gagné ou perdu)
RevealMines
movem.l d0-d3/a0-a2/a6,-(sp)
lea Mines.Array(pc),a2 ; La grille des mines
moveq #-1,d2 ; La position actuelle dans la grille
move.l Intuition.Base(pc),a6
move.l Width(pc),d3
mulu Height+2(pc),d3 ; d3 est la taille de la grille
RevealLoop
addq.l #1,d2 ; incrémente la position
cmp.l d3,d2 ; havons nous atteint la fin de la grille ?
beq.s EndOfReveal ; oui...alors fini.
tst.b (a2)+ ; y a-t-il une mine ici ?
beq.s RevealLoop ; Non, position suivante
move.l d2,d0 ; oui! sa position est en D0
divu Width+2(pc),d0 ; pour séparer les coordonnées X et Y
moveq #0,d1 ; abscisse (le reste de la division) en D0
move.w d0,d1 ; ordonnée en D1 (le quotient de la division)
clr.w d0
swap d0
move.l YAMFG.RastPort(pc),a0
lea Mine.Image,a1 ; structure Image pour une mine
lsl.l #4,d0 ; Change X et Y de la grille en véritable coordonnées
lsl.l #3,d1 ; graphiques
add.l PlayX(pc),d0
add.l PlayY(pc),d1
jsr _LVODrawImage(a6) ; Dessine une mine
bra RevealLoop ; contine avec les autres positions
EndOfReveal
movem.l (sp)+,d0-d3/a0-a2/a6 ; toutes les mines affichées,on a
rts ; fini notre travail
; Cette routine est appelée quand le menu correspondant est sélectionné
QuitYAMFG
addq.l #4,sp ; Pas de retour pour cette routine
bra ClearMenus ; Nous partons!
; Appelé quand le joueur a chois 'About' dans les menus
ShowAbout
movem.l d0-d1/a0-a4/a6,-(sp)
lea About.Body(pc),a1 ; message principal
lea About.Gad(pc),a2 ; Texte pour le gadget
suba.l a3,a3 ; pas de structure ReqInfo
move.l a3,a4 ; et pas de formattage
lea About.TagList(pc),a0 ; TagList spécifique
move.l ReqTools.Base(pc),a6 ; Laissons la reqtools.library
jsr _LVOrtEZRequestA(a6) ; le faire...
movem.l (sp)+,d0-d1/a0-a4/a6
rts
; Quand l'utilisateur veut changer le nombre de mines (avec le menu)
ModifyMines
lea Mines(pc),a1 ; Variable qui contient le nombre de mines
lea HowManyMines.Title(pc),a2 ; Titre pour le requester
suba.l a3,a3 ; pas de ReqInfo
lea Mines.TagList(pc),a0 ; mais quelques tags...
move.l ReqTools.Base(pc),a6 ; Demande le nombre de mines
jsr _LVOrtGetLongA(a6)
tst.l d0 ; l'utilisateur a entré un nombre valide ?
bne.s NewMines ; oui, nouvelle partie
rts ; non, requester annulé
; Il veut changer la largeur de l'aire de jeu
ChangeWidth
lea Width(pc),a1 ; Variable pour la largeur
lea Width.Title(pc),a2 ; Titre du requester
sub.l a3,a3
lea Width.TagList(pc),a0 ; quelques tags...
move.l ReqTools.Base(pc),a6
jsr _LVOrtGetLongA(a6) ; Nouvelle largeur demandée
tst.l d0
bne.s NewWidth ; Nouvelle partie si c'est valide
rts ; retourne si le requester a été annulé
NewMines ; un branch pour les routines qui nécessitent une nouvelle
NewWidth ; partie
NewHeight
addq.l #4,sp ; corrige la pile pour l'adresse de retour
bra NewGame ; et branche sur le programme principal
; Exactement la même routine que ChangeWidth(). Je ne crois pas que des
; commentaires soient nécessaires.
ChangeHeight
lea Height(pc),a1
lea Height.Title(pc),a2
sub.l a3,a3
lea Height.TagList(pc),a0
move.l ReqTools.Base(pc),a6
jsr _LVOrtGetLongA(a6)
tst.l d0
bne.s NewHeight
rts
; Cette partie contient des données pour les fenêtres,menus,messages,et
; quelques petites choses diverses.
YAMFG.NewWindow ; la structure NewWindow
dc.w 120,0 ; origine XY
dc.w 400,200 ; Largeur et hauteur en pixels
dc.b 0,1 ; couleurs FrontPen et BackPen
dc.l IDCMP_CLOSEWINDOW!IDCMP_RAWKEY!IDCMP_MENUPICK
; La ligne ci-dessus contient les flags IDCMP, un message sera envoyé par
; Intuition à notre programme quand ces évenements arriveront.
dc.l WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!ACTIVATE!NOCAREREFRESH
; Ce sont des flags standards pour les fenêtres. Il n'y a pas de flag exo-
; tique,ils sont évidents par leur nom,vous devriez les comprendre vous-
; même,donc pas besoin de commentaires supplémentaires, alors pourquoi
; est-ce que je vous ennuie avec ça ?
dc.l 0 ; Pas de gadgets sur cette fenêtre
dc.l 0 ; Pas de CheckMark particulier (on n'en utilise même pas)
dc.l YAMFG.WindowName ; Nom de notre fenêtre
dc.l 0 ; Ecran: on se contentera de celui du Workbench
dc.l 0 ; Bitmap: pas de bitmap.
dc.w 400,200 ; dimensions minimales (inutiles ici)
dc.w 400,200 ; dimensions maximales (idem)
dc.w WBENCHSCREEN ; oui,l'écran du workbench
YAMFG.Border ; structures Border pour le rectangle autour de l'aire de jeu
dc.w -1,-1 ; origine XY
dc.b 1,0,RP_JAM1,3 ; FontPen,BackPen,DrawMode,Nombre de vecteurs
dc.l YAMFG.Vectorsa,YAMFG.Borderb ; Vecteurs,border suivant
YAMFG.Borderb
dc.w -1,-1 ; on utilise 2 borders pour créer un effet
dc.b 2,0,RP_JAM1,3 ; de pseudo-3D (un coté en blanc,l'autre en
dc.l YAMFG.Vectorsb,0 ; noir)
YAMFG.Vectorsa ; Les coordonnées pour les vecteurs du premier border
dc.w 0 ; Certaines seront changées par le programme.
Border.Bot1
dc.w DEFAULT_HEIGHT*8+1
dc.w 0,0
Border.Right1
dc.w DEFAULT_WIDTH*16+1,0
YAMFG.Vectorsb ; Même chose pour le second border
Border.Right2
dc.w DEFAULT_WIDTH*16+1,1
Border.Right3
dc.w DEFAULT_WIDTH*16+1
Border.Bot2
dc.w DEFAULT_HEIGHT*8+1
dc.w 1
Border.Bot3
dc.w DEFAULT_HEIGHT*8+1
Project.Menu ; Voici la structure menu pour le menu project
dc.l Options.Menu ; Menu suivant: 'Options'
dc.w 0,0 ; Bord gauche et haut
dc.w 63,0 ; Largeur et hauteur (Hauteur inutilisée)
dc.w MENUENABLED ; Flags: le menu est autorisé
dc.l Project.Name ; devinez ce que c'est
dc.l About.MenuItem ; Premier item de ce menu
dc.w 0,0,0,0 ; variables Intuition mystérieuses
About.MenuItem ; structure MenuItem pour l'item 'About'
dc.l Quit.MenuItem ; Item suivant
dc.w 0,0 ; Bord gauche,Bord haut
dc.w 104,8 ; Largeur,Hauteur
dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP ; menu flags:
; ITEMTEXT signifie qu'une structure IntuiText sera utilisée (ç'aurait pu
; être une Image),COMMSEQ signifie qu'il y a un raccourci clavier,ITEMENABLED
; que l'item peut être sélectionné,HIGHCOMP dit à Intuition d'inverser les
; couleurs du menu si le pointeur de souris passe dessus
dc.l 0 ; Pas d'exclusion mutuelle
dc.l About.IText ; Render: une structure IntuiText
dc.l 0 ; Pas de rendering pour l'état sélectionné
dc.b 'A' ; Raccourci clavier
dc.b 0 ; Un octet de remplissage pour avoir une adresse paire
dc.l 0 ; pas de liste de SubItems
dc.w MENUNULL ; sera rempli par Intuition pour la sélection
; étendue
dc.l ShowAbout ; Champ non standard,utilisé par le prog
; pour determiner la routine à executer quand le menu est sélectionné
About.IText ; Une structure IntuiText pour le MenuItem
dc.b 3,1,RP_COMPLEMENT,0 ; DetailPen,BlockPen,DrawMode,FillByte
dc.w 0,0 ; Bord gauche,Bord haut
dc.l 0 ; fonte par défaut
dc.l About.MSG ; Message
dc.l 0 ; Pas d'autre structure IntuiText
; Les autres Menus et MenuItems sont faits de la même façon,ce serait une
; perte de temps de tous les décrire.
Quit.MenuItem
dc.l 0
dc.w 0,8
dc.w 104,8
dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
dc.l 0
dc.l Quit.IText
dc.l 0
dc.b 'Q'
dc.b 0
dc.l 0
dc.w MENUNULL
dc.l QuitYAMFG
Quit.IText
dc.b 3,1,RP_COMPLEMENT,0
dc.w 0,0
dc.l 0
dc.l Quit.MSG
dc.l 0
Options.Menu
dc.l 0
dc.w 70,0
dc.w 63,0
dc.w MENUENABLED
dc.l Options.Name
dc.l Mines.MenuItem
dc.w 0,0,0,0
Mines.MenuItem
dc.l Width.MenuItem
dc.w 0,0
dc.w 184,8
dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
dc.l 0
dc.l Mines.IText
dc.l 0
dc.b 'M'
dc.b 0
dc.l 0
dc.w MENUNULL
dc.l ModifyMines
Mines.IText
dc.b 3,1,RP_COMPLEMENT,0
dc.w 0,0
dc.l 0
dc.l Mines.MSG
dc.l 0
Width.MenuItem
dc.l Height.MenuItem
dc.w 0,8
dc.w 184,8
dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
dc.l 0
dc.l Width.IText
dc.l 0
dc.b 'W'
dc.b 0
dc.l 0
dc.w MENUNULL
dc.l ChangeWidth
Width.IText
dc.b 3,1,RP_COMPLEMENT,0
dc.w 0,0
dc.l 0
dc.l Width.MSG
dc.l 0
Height.MenuItem
dc.l 0
dc.w 0,16
dc.w 184,8
dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP
dc.l 0
dc.l Height.IText
dc.l 0
dc.b 'H'
dc.b 0
dc.l 0
dc.w MENUNULL
dc.l ChangeHeight
Height.IText
dc.b 3,1,RP_COMPLEMENT,0
dc.w 0,0
dc.l 0
dc.l Height.MSG
dc.l 0
About.TagList ; Les tags pour le requester "about"
dc.l RT_IDCMPFlags,IDCMP_MOUSEBUTTONS!INACTIVEWINDOW
; Des flags IDCMP supplémentaires pour réagir
dc.l RTEZ_Flags,EZREQF_CENTERTEXT ; Centre le texte
dc.l TAG_END
Mines.TagList ;Tags pour le requester "nombre de mines"
dc.l RTGL_Min,1 ; Minimum 1
dc.l RTGL_Max,100 ; Maximum 100
dc.l TAG_END
Width.TagList ; Pour le requester de la largeur
dc.l RTGL_Min,4 ; Minimum 4
dc.l RTGL_Max,MAX_WIDTH ; Maximum
dc.l TAG_END
Height.TagList ; Pour le requester de la hauteur
dc.l RTGL_Min,4 ; Minimum
dc.l RTGL_Max,MAX_HEIGHT ; Maximum
dc.l TAG_END
Project.Name ; Pas besoin de commentaires
dc.b 'Project',0
About.MSG
dc.b 'About...',0
Quit.MSG
dc.b 'Quit',0
Options.Name
dc.b 'Options',0
Mines.MSG
dc.b 'Number of mines...',0
Width.MSG
dc.b 'Width...',0
Height.MSG
dc.b 'Height...',0
YAMFG.WindowName
dc.b 'YAMFG 1.0 © 1993 F.Delacroix -FreeWare',0
ReqTools.Name
dc.b 'reqtools.library',0 ; Nom de la reqtools.library
Space.Text
dc.b ' ' ; Utilisé pour effacer l'image du tank
Lost.MSG
dc.b 'You blew up ! Press a key...',0
MinesNumber.MSG
dc.b 'Number of mines around you:'
Mines.Number
dc.b '0',0
Won.MSG dc.b 'Congratulations! You''ve reached the goal!',0
About.Body ; The about message,please dont change this.
dc.b 'YAMFG 1.0 by F.Delacroix - FreeWare',10,10
dc.b 'This program may not be used for any profit',10
dc.b 'To contact me,write to:',10
dc.b 'Frédéric DELACROIX',10
dc.b '5 rue d''Artres',10
dc.b '59269 QUERENAING, FRANCE',0
About.Gad
dc.b 'Ah-ha.',0
HowManyMines.Title
dc.b 'How many mines ?',0
Width.Title
dc.b 'New width ?',0
Height.Title
dc.b 'New height ?',0
WBStarter dc.l 0 ; WBStartup reçu (0 si CLI)
Graphics.Base dc.l 0 ; Base de la graphics.library
Intuition.Base dc.l 0 ; Base de l'intuition.library
ReqTools.Base dc.l 0 ; Base de la reqtools.library
YAMFG.Window dc.l 0 ; structure Window (pas NewWindow)
YAMFG.RastPort dc.l 0 ; RastPort de notre fenêtre
YAMFG.UserPort dc.l 0 ; Son UserPort
Mines dc.l DEFAULT_MINES ; Nombre de mines
MinerX dc.w 0 ; Abscisse du tank (de 0 à width-1)
MinerY dc.w 0 ; Ordonnée du tank (de 0 à height-1)
Width dc.l DEFAULT_WIDTH ; Largeur (en colonnes)
Height dc.l DEFAULT_HEIGHT ; Hauteur (en lignes)
PlayX dc.l 0 ; Offset graphique pour l'aire de jeu
PlayY dc.l 0
Mines.Array dcb.b MAX_WIDTH*MAX_HEIGHT,0 ; Matrice qui contient les
; positions des mines. Notez que seule une partie sera utilisé car Width et
; Height peuvent ne pas être MAX_WIDTH et MAX_HEIGHT
FinishFlag dc.b 0 ; Flag mis quand le jeu est terminé
section Images,DATA_C
; Voici des structures qui doivent être en CHIP-ram:
Tank.Image ; structure Image pour le tank
dc.w 0,0 ; Bord gauche,Bord haut
dc.w 16,8 ; Largeur,Hauteur
dc.w 2 ; Profondeur: 4 couleurs
dc.l Tank.ImageData ; Données pour l'image
dc.b $0003,$0000 ; Modèles pour les bitplanes
dc.l 0 ; Image suivante:aucune
Tank.ImageData
dc.w $0000,$001F,$0000,$7FFE,$FFFF,$FFFF,$FFFF,$7FFE
; Données pour le premier bitplane
dc.w $07C0,$0FE0,$0FE0,$7FFE,$FFFF,$8001,$7FFE,$0000
; Données pour le second bitplane
Mine.Image ; Structure Image pour une mine
dc.w 0,0
dc.w 16,8
dc.w 2
dc.l Mine.ImageData
dc.b $0001,$0000
dc.l 0
Mine.ImageData
dc.w $0000,$0000,$0000,$0000,$0FF0,$7FFE,$7FFE,$0000
; Un seul bitplane ici
Target.Image ; Structure Image pour la cible
dc.w 0,0
dc.w 16,8
dc.w 2
dc.l Target.ImageData
dc.b $0003,$0000
dc.l 0
Target.ImageData
dc.w $07E0,$0FF0,$1FF8,$3E7C,$3E7C,$1FF8,$0FF0,$07E0
dc.w $07E0,$0C30,$1818,$318C,$318C,$1818,$0C30,$07E0